#pragma once

#include <iostream>
#include <string>
#include <unordered_map>
#include <cstdlib>
#include <sys/epoll.h>
#include <unistd.h>

// 一般处理IO的时候，我们只有三种接口需要处理
// 处理读取
// 处理写入
// 处理异常
#define SIZE 128
#define NUM 64

class Event;
class Reactor;

typedef int (*callback_t)(Event *ev); //函数指针类型

// 需要让epoll管理的基本节点
class Event{
public:
    int sock;//对应的文件描述符
    std::string inbuffer;//对应的sock,对应的输入缓冲区
    std::string outbuffer;//对应的sock,对应的输出缓冲区

    // sock设置回调
    callback_t recver;
    callback_t sender;
    callback_t errorer;

    // 试着Event回指Reactor的指针
    Reactor *R;

public:
    Event(){
        sock = -1;
        recver = nullptr;
        sender = nullptr;
        errorer = nullptr;
        R = nullptr;
    }
    void RegisterCallback(callback_t _recver, callback_t _sender, callback_t _errorer){
        recver = _recver;
        sender = _sender;
        errorer = _errorer;
    }
    ~Event()
    {}
};

// 不需要关心任何sock的类型(listen，读，写)
// 如何进行使用该类，对Event进行管理
// Reactor : Event = 1 : n;
class Reactor{
private:
    int epfd;
    std::unordered_map<int, Event*> events; //我的Epoll类管理的所有的Event的集合
public:
    Reactor() : epfd(-1)
    {}

    void InitReactor(){
        epfd = epoll_create(SIZE);
        if (epfd < 0){
            std::cerr << "epoll_create error" << std::endl;
            exit(2);
        }
        std::cout << "InitReactor success" << std::endl;
    }

    bool InsertEvent(Event *evp, uint32_t evs){
        // 1. 将sock中的sock插入到epoll中
        struct epoll_event ev;
        ev.events = evs;
        ev.data.fd = evp->sock;
        if (epoll_ctl(epfd, EPOLL_CTL_ADD, evp->sock, &ev) < 0){
            std::cerr << "epoll_ctl add event failed" << std::endl;
            return false;
        }
        // 2. 将ev本身插入到unordered_map中
        events.insert({evp->sock, evp});
    }

    void DeleteEvent(Event *evp){
        int sock = evp->sock;
        auto iter = events.find(sock);
        if (iter != events.end()){
            epoll_ctl(epfd, EPOLL_CTL_DEL, sock, nullptr);// 1. 将sock中的sock从epoll中删除它
            events.erase(iter);// 2. 将特定的ev从 unordered_map中 移除
            close(sock);// 3. close
            delete evp;//4. 删除event节点
        }
    }

    //关于修改，也是最后看, TODO, 使能读写
    bool EnableRW(int sock, bool enbread, bool enbwrite){
        struct epoll_event ev;
        ev.events = EPOLLET | (enbread ? EPOLLIN : 0) | (enbwrite ? EPOLLOUT : 0);
        ev.data.fd = sock;

        if (epoll_ctl(epfd, EPOLL_CTL_MOD, sock, &ev) < 0){
            std::cerr << "epoll_ctl mod event failed" << std::endl;
            return false;
        }
    }

    //如果再调用recver回调函数的时候，就出错了，就会执行error的回调函数，删除event事件，关闭fd
    //后续派发sender回调函数的时候，就会报错
    bool IsSockOk(int sock){
        auto iter = events.find(sock);
        return iter != events.end();
    }

    //就绪事件的派发器逻辑
    void Dispatcher(int timeout){
        struct epoll_event revs[NUM];
        int n = epoll_wait(epfd, revs, NUM, timeout);
        for (int i = 0; i < n; i++){
            int sock = revs[i].data.fd;
            uint32_t revents = revs[i].events;
            //代表差错处理, 将所有的错误问题全部转化成为让IO函数去解决
            if (revents & EPOLLERR)
                revents |= (EPOLLIN | EPOLLOUT);
            if (revents & EPOLLHUP)
                revents |= (EPOLLIN | EPOLLOUT);

            //读数据就绪,可能会有bug，后面解决
            if (revents & EPOLLIN){
                //直接调用回调方法，执行对应的读取
                if (IsSockOk(sock) && events[sock]->recver)
                    events[sock]->recver(events[sock]);
            }
            if (revents & EPOLLOUT){
                if (IsSockOk(sock) && events[sock]->sender)
                    events[sock]->sender(events[sock]);
            }
        }
    }

    ~Reactor() {}
};
